{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "81300cce",
   "metadata": {
    "id": "81300cce"
   },
   "source": [
    "# Fine Tuning with PyTorch\n",
    "- Using CIFAR-10 Dataset to first train a model from scratch\n",
    "- then train a model by Fine Tuning a pretrained VGG11 model\n",
    "- and then compare the results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "80688c50",
   "metadata": {
    "id": "80688c50"
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "from collections import defaultdict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "uAuSPLa1lh4E",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "uAuSPLa1lh4E",
    "outputId": "b9a57b75-b00c-4775-db0b-cc2f1f28e256"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.cuda.is_available()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "sZt60TqQllVw",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "sZt60TqQllVw",
    "outputId": "53ae5403-294f-49a9-fcaa-3583e31e41ae"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda', index=0)"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n",
    "device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "4n24U4hniz3j",
   "metadata": {
    "id": "4n24U4hniz3j"
   },
   "outputs": [],
   "source": [
    "ACCURACY_COMPARE = defaultdict(dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ad3484f",
   "metadata": {
    "id": "8ad3484f"
   },
   "source": [
    "#### Define Transforms and Load Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "48c15d77",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "48c15d77",
    "outputId": "2add4b6f-277c-4773-d88b-0eb8e51ee55f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "transform = transforms.Compose(\n",
    "    [transforms.ToTensor(),\n",
    "     transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))])\n",
    "\n",
    "batch_size = 256\n",
    "\n",
    "trainset = torchvision.datasets.CIFAR10(root='./data', train=True,\n",
    "                                        download=True, transform=transform)\n",
    "trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,\n",
    "                                          shuffle=True, num_workers=2)\n",
    "\n",
    "testset = torchvision.datasets.CIFAR10(root='./data', train=False,\n",
    "                                       download=True, transform=transform)\n",
    "testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,\n",
    "                                         shuffle=False, num_workers=2)\n",
    "\n",
    "classes = ('plane', 'car', 'bird', 'cat',\n",
    "           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "778b3ce7",
   "metadata": {
    "id": "778b3ce7"
   },
   "source": [
    "#### Image Samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "de7df48b",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 248
    },
    "id": "de7df48b",
    "outputId": "1978fa1f-3878-4109-851d-9dbef76a6475"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAACwCAYAAACviAzDAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA90ElEQVR4nO2de3RV1bX/Z07OI4c8TghpEgIJUEQRUUReRq1STX3U66NSr/qzV3y0Xr1gBe6tis/b9loc7fhV216qv1aL9lbEYgWtD7wUEF+8BRUpiIgQgSSGmOQQDue19++PtnvNOQ9nJyeGE0K+nzEyxlpn7r322muvvVms+cqxbdsmAAAAAIAs4enpDgAAAACgb4HFBwAAAACyChYfAAAAAMgqWHwAAAAAIKtg8QEAAACArILFBwAAAACyChYfAAAAAMgqWHwAAAAAIKtg8QEAAACArILFBwAAAACyyhFbfMydO5eGDh1KeXl5NGnSJFq7du2RuhQAAAAAehE5RyK3y7PPPkvXXXcdPfbYYzRp0iR65JFHaOHChbRt2zYqKytzPdeyLNq7dy8VFhZSTk5Od3cNAAAAAEcA27YpHA5TZWUleTwd7G3YR4CJEyfa06ZNc+rJZNKurKy058yZ0+G5dXV1NhHhD3/4wx/+8Ie/XvhXV1fX4b/1XupmYrEYbdiwgWbPnu385vF4qLa2llatWpVyfDQapWg06tTtv2/EzJw5kwKBQHd3DwAAAABHgGg0Sg8//DAVFhZ2eGy3Lz6ampoomUxSeXm5+L28vJy2bt2acvycOXPohz/8YcrvgUAAiw8AAACgl9EZk4ke93aZPXs2tba2On91dXU93SUAAAAAHEG6feejtLSUcnNzqaGhQfze0NBAFRUVKcdjhwMAAADoW3T7zoff76dx48bRsmXLnN8sy6Jly5ZRTU1Nd18OAAAAAL2Mbt/5ICKaNWsWTZ06lcaPH08TJ06kRx55hNrb2+mGG2740m3/8OcH5A9Jtn7KjaujE+kbSqp6rovMDcvq/LEduR6lazeja3T4Q5prqLHTY2DzPuj+sGnkV6JYRFQvv+UapzymfH3arr3o+U9Rt1R/LP681C1G2a3EOhi6JJMn1BBYLresHwmvJrWM9T2hZcbWmpIxKdP9sckFPtWjLjIiIt5uRF2EPy59nr7pOLtQVD5nipmbeeBfnyA3rv7P/3TKqzbLHdMv6hudcn4wKLt6QF6zrNy48Xu8uULG3f7yA7KdmuGyXuLS1y3sIdTvkZOSX3NE6iav4N3t7U558KB8ITulnynLuyDapeo79ppyNCLHo7TU3NeQkDxPBzzg7erpczx1nv9kzzITGehddMezPCKLj6uuuoo+//xzuv/++6m+vp5OPfVUWrJkSYoRKgAAAAD6Hkdk8UFENH36dJo+ffqRah4AAAAAvZQe93YBAAAAQN/iiO18HDHCzeoHvn7S2soMbCVcz3NrJ5NreNKUO7qmNsDo6jX1eVyp39E13K7JplGKkUWrqL29dodTHnNJ+hYDynYkxY6C35ZWjLstqV1sN3LVeUkXs5sUGxQm9+hj2fB4lB0FH66OzHWEdUZXp4Am4VN1l2P1TZPbAOmHkp4/LH7HKa9c946Q8a6Hm+S7H4mmGKU4pVxlX+VhD9dS54VUQCSPzzwwPXSRqLFlSWijHEbALz348vOlXQfvT0XFQCELMtsWHoCRiKj5CzkGJf2NhYqlnkE43MauXyBkFSrNhSfXnFuo+nri6NFOecjQYiGbgAwYoItg5wMAAAAAWQWLDwAAAABkld6ndqEqF1kGrrau+9ZfRs3RSfVERu10l9rHbXx0O+m3lFNxU+3I9W1+Md/S/SJ9kx3s2nuYPOWK7JJaBZLa0OHP0w2735X7U3Drg5c1ZPnSH9fhRbqKRz1nr8tF9GvB1Q56QDJwKw8WmDkRKimWMr9RQWj1yOfNcv7EWX90Rk2ukkj45XehNabdhNP3lbfr9csHFlSuwJw2dY2SEqMuiSg390i7qWtVSm5QqnMS7D1oapUqmfY2487rzZd9KyyVDsWhgjynrB9dgvUhCDUL6Caw8wEAAACArILFBwAAAACyChYfAAAAAMgqvdDmQ8fv5sYB+na6y+YjvUufO24x3FOU5C7tZOKG64bb+GgbD31sVw0OikUtz6ef3+HxquFIMSHgthL6ZBcTlBRv0TSnEclQ6Pr6GVkB8XP1VGIy7Siu7V64ut12M0LRN6LtZ/ijTbrMO22sovvODQ6S6iK+zs/LylLj9lkWKhWyUAGz8/iKPK+oWNk4RIyNQ1LHsWfEVBhy7cfN7Syi0Xhamdcn35Egs6vQNietLdLl3O21DXiNLYlf+Zx7fNLOxMeuo8Orl5WYsayoHCRkFeXS1baM2dN4Vd/9zJYlqWP8Z2AD8hErq9FImbLBNGUiOQ20mRRSlPYesPMBAAAAgKyCxQcAAAAAsgoWHwAAAADIKr3P5iOnWNZtfgspSukuXqSjeCFuMTD4ek4HDOCyQiXLxK7ETZ+eSUwQXs8kRoobuh0ZqjkQLOpUK242HoetM3yJ9IdZKT+wY9Xw5DKFclINeUK/OUzuUYpoYaHjEoU8JTmAuoboum6HXVOr5V3RYdBz+YCkHKw6xA5IiVHS+f/XWCxkuTbKsdiA5as4GoPLZFjycHsbpcPvM9YAh5RthO5pc3Nz2mPjcTO5PAF5po/ZY1hqwuSr+BweNpYBZZSTHzD3madCnesxyGd2JpWl0l6msNh8YwoLi4UsGJD98frMvYQK5Ts6pL8pZxL9R+MSPoXaVZ3ftX4+n7FyR7YjrOsp9iD8WGUFlNIu/xrqa/D31i1Uj/766k+I2z1zmb6PMuqdYOcDAAAAAFkFiw8AAAAAZJXep3ZRW4ti/zuhVAVJVXfzsxRhjPV5arNR750L+KaYmypDqV18auMx7nIN4WfZkUtjZ9Uw3RVeXW+uqnbyOudq6+loZrKd6pRw0Gl6RpSafJU/Sjf3Xj06PjVF4i7LeLdR5mogHdlcX0Oc7KKG0uob2y3rbyaZBLTOSuz/dv3/MfzM1ma14c3i6AeU22mhytSqs7HKZsxVtCpFU8jcTrWLbDgcdsr+Qtkf7oYb0ddQz8DvNYOXH5T97sfuw6fceVPGgIVF12EIuMuuntt+v2yXT7WIytZrMWXCcdR1uAokT8lCqs6TaOhPQVOaMlGqMps7GOsvTz0rH1IytxmS8i1wuT4fSX0NfV+8rq8RdpE1qno0TZlIPmd9/SGqrlVh3Q12PgAAAACQVbD4AAAAAEBWweIDAAAAAFml99l8VMkwwRRj66e4si/QNiBc4a+P5TJLacpSbDy4li8l/zRrx0Vr5lFaTq9yoBLtKMU872uK76YOic3PdTF4SInXnYnNB1doay2jbMfjS592nBNwGQ4iZaqgZF5t45D+ULdI7OIxaxOclHZYQ3ra5bLORrXimb2BPjcFrcLlFlP6mtTXDDKNtqWEET631RzQxjXcSKWr0ffVqdGYHIRw2LjPFgaUm6lyO+Xhzn1e+WnzswmVr2xDdCh07jIbV98Jbi/iDcinkGC2YdrmIxGXD9PP7iURkdeIMtdjbfOhibF2/epYYWukvgsJNUl5tVDZoGSSwMENbq2XkkpA4faV4J8G7WZakUE7/F8SN9dWImkv4uYyrG1Z+LH6i6r7zh2c9Zhz+xT9WdD/yvB6s5Lx+9TX/0zVeR+063F3gJ0PAAAAAGQVLD4AAAAAkFV6ndql31ekq+3BqFk/5aitRdtNDZN0UbskOtgUtNjGX1xueuWwLe1TTx4uZNs/NY5hB+rVhqBWu1guW9r8viy1CZdQG3ZCLaNVMvwaHegVeMTGlGNdYgXGZP8Cgc5FOPWr4fDqx8XLLlv+HSmT3NxyXRKjpq7aPellvBmtEgoyodrFT4lwKp6sksXY/m5QyaIpEVfNKFhKdZGifePoELD8RnO1rPN6mFChUUFqFUiCqSD2N8tNZK2SyGMqiGCKSoa5nSqVjFbDuMm8zNVfR7L1sYebVKrSWFRt1rPhaW+X35v2dvNN0X1NcRO2mIrGKzsUKjbj6lUyrYYJBI1iIRRSEVdZ+UsktRXqki+TfbYkTfnLMLDjQxz0GHzKyu8q2fbtphxpkTIVSJYqmCZ++1b5nD/c8oFTbm76QsgiURnZN8FeoXb1NfK2mnO/f9U1QnbtmXKuf87KYep+sPMBAAAAgKyCxQcAAAAAskrGi4833niDLrnkEqqsrKScnBxavHixkNu2Tffffz8NHDiQgsEg1dbW0na+9wQAAACAPk3GNh/t7e00ZswYuvHGG+mKK65Ikf/0pz+lX/7yl/TUU0/RsGHD6L777qMLLriAtmzZQnl52hEpc/qr8Op+ZvORq8KgJ5V7W4LpOS0VQphnq7SUzYellLs2s3Hop4wIbr9yglO+a6ZU6j37mil//4G3hOxQinMXdwtWIq79136d6r6EzUeKrYbbNRS8XbfQ77nKXqZdHusN6gDEh8enlsVxrV938ZF1cS5O8RblIcxTvK/5sR28KR7Wjg6Tzs/1urjPxlTfEsosiHcvpvrKVfr9lQ7YikiNbcIy71C7uq929nhsv0vceiI59yLquWfw35pBVcVO+WBEBqHuV2jei2hM6sEbG2RgaW7joOc6d33NzZWdi4WKRV20o7D4PafYRZkfuLsuEZFPuQm3s/HyKgOnIOt7NOpuf8Zddv06Uy2bFEGVVTehbMO82oCFwZ/I50rWWzOqZsp7rPy7p/YI2YrVLznlLTs3CFnywzpT0d/qoLLfYRmKqU3Jdr/DKtrqpL+olV9+sVMuGyn/vdz+181O+e6ZfxKy76x9VdTL0pSJiF6gL0/Gi4+LLrqILrroosPKbNumRx55hO6991667LLLiIjo97//PZWXl9PixYvp6quv/nK9BQAAAECvp1ttPnbu3En19fVUW1vr/BYKhWjSpEm0atWqw54TjUapra1N/AEAAADg2KVbFx/19X+Lw1ZeXi5+Ly8vd2SaOXPmUCgUcv6qqqoOexwAAAAAjg16PM7H7NmzadasWU69ra3NdQFSHJL6LV/C+KR7lG+9J8Xmw+hPtX6/osD41hfmS/3s7n0yBHWYhaAeP1TaMNx6o7HzsA7Ka3zza6a85BsyBsiSdVKB7GfGAbnaPoWVU1I/x5W9CrdzUTFBbG67ofX5Or4vt4NJsSth+uJcJfPLhoN56WMqcHTYE4+2SeGhCFRfPS5mLj7VbpK147YSj+sYHErObVC0XQkfWy3jdiXKZCk1ujq/qLaB4XEjdi0XsqYPPhH1sqopTjn/eJlIO8r745E3rUPK2FGXIO8ZxPngQ9LcLJOkc5uHoLJpaA/I2d/ObEIicRlXQ6SiV11ra5exenhI93wVjCG/wHwbCvPkd0Gaism+6fglvAt6qLzsWG3x4VXPhIeR93plf/i7r208kjocEPtuNDfLfxYSQTPZ/GrelfWjY5IF2+WcWPnOWqf82IP/Iw9u2eoUT77ybCH6oG6LqeyR/wE/+4pLRP2zOhPgvLlZzpeW3drOg5EjJ9A3v3GSKd9cI2TbNp/slO+tuVW201on66EjuxHQrTsfFRV/i6zf0NAgfm9oaHBkmkAgQEVFReIPAAAAAMcu3br4GDZsGFVUVNCyZcuc39ra2mjNmjVUU1PjciYAAAAA+goZq10OHDhAH3/8sVPfuXMnbdq0iUpKSqi6uppmzJhB//Vf/0UjRoxwXG0rKyvp8ssv75YO9yuS2458O95r6W1gtW3sMdu2wZjcd7zmLLPjMmGUbGXBCln/3w0shPpY6ZbHPAPps51yHz1UZvYsr5oiA/pu2qUMbZmbnFepOfgmW0TvIWs9QzL91muC7aPraPMpWS/j5tyk2n8X2q2k2ij2y+1vvm3tlgk1qJKtWm7LZDWL4y7ekJoYO0CrRPguf0fR5z1saD2qP0K1ok4ULsTqPI+KyM0P1a7ISaYq2PPRO0Jm7/hY1Fut451yxUipdiliF9EJk7UaSGSjVQGz9ba+G342JRJRORHbPWb7O6JcbXXSaB6KvLFFhmIPMlVqnkf2VbvechWJDkteXGTUrIMrZIZtHord0ipgpS7hGWh92s2Vq/DccgcQkUecK++jtYWNXUSqs3T/QmzHWavXwmHTrqVm/rgRxa796y1o9XVju3SnvWbq153y73//RyE74cLJTvnGf7lSyP5v3Q7TZr4c2EYmIyL65M9/NpXqUzvoMcOWOWffXGRiOow6XX5Ihw83apcBo04RskWP/0bUv/XvP+58H7pAxouP9evX09e/bh7EP+w1pk6dSk8++STdcccd1N7eTjfffDO1tLTQWWedRUuWLOmWGB8AAAAA6P1kvPiYPHky2XZ645ecnBz60Y9+RD/60Y++VMcAAAAAcGyC3C4AAAAAyCo97mqbKUUq8jEPj52yknLJ/H5CvtTBnnmcKZe0bxWyC08bKer1YTNso4bJdr6oNzrrnbuknjXYXOyUJ02S7rznTJBePu/uZOd55LFJds86ELTWEIvU88qug3vaaj1vitsn+yHuEraeLGm70hSWhguhEHNNlpmhBTq9fEfR3wXcxkKJkuo+uZ2HVr3zl8OvbRj03GJmBDE9luxe9H0EuK2ImsA6ED2f63nqza3fZcImxz/epc6UOuFDzeZYT+I8eU2fmWu6P1E1PjzsdopNjEsYeU1jvRmEvKCKKc+MW3QaeH1Rbqekj+Uuuz5lC6bdYD256f9P1thoPPka9+wTskKdI50RV3ZbPmZLUpgv3c+9zB5E34elDHG8zDDJ45OT4mCbCauv3Yk1Q6oGO+XSEpmovoW1Ew7LUP3njrjAtd3ewst75fice+rxaY4kOtjyqaiXVRi7qXtm3iVkbW//r1POHXGikG1dt5bSsntnelkHfPyX153yD2pfF7KLZkx3ytFDBUK24E8rRf1b/97lLnQK7HwAAAAAIKtg8QEAAACArILFBwAAAACySq+z+RggXeupnYWV8KUEX5BVHiJbJ5CubzD2GRXF0m7h1Ep57OTjjQ69MiCHsK3J6ERbD8iYF1HWoegXUrd95fnyGl+8aMpJndmcqY9TbDxc4lEoUw3ZjpLFlY2DlTAjlkjI0eMhAzwk/cr9hbJD/UvYuS42H9reIH3C78yw1Izn2n/9MvCwEipMAqkM5RRkavuAjjviEueD36eydqBir5w//anFHOuTOuq/NK42lVgLSbTxhon7YUVkWvrKMhb3I6rCjsdkO80soEn8Szyh1hbzPpWWyxTgPN28FVMxQKIyOkMint7mQ9t1CJlLnA+fivORx1LYe1WbkYjpj26Ty4ik7UZza4uUsfvQ/dbxd7gdmzegw70be6u4iuuRq+xeYqx/nym7myj7ULS3SZuPrft7r83HC8wcLVAp7W50YIj1YfYBULZ827cYO6C2tzdTOpLbd6hfXEKmUzclWFXf2Fcf+O+0h66k/uoX/v53Li1GJmDnAwAAAABZBYsPAAAAAGSVXqd2KZNRySnMdqbVTngK7WyppV0u328ywkrl+rbtxadF/ad3322uf1BuQ1713Vuc8viLrxMyvpW3f4/cVvvaaOmm9/5YU96utvwTLtv4OsOrm9qFu9MmtNpF+YTy6yS0aoc9A48lt6nzVdzi4mJTdtt09OsQ5R2EN+fw8OY6Y6jOjlvK/FnblezPry52ylvf+1DIxo2R7teTRhvXvPzSMiELk3Fp83jk1njQMnu/3oR80OF98po7WIbMsnK5NV7hMeceP0Bmo4wpV9tP9xtVi3/fe0J24jAzgRIqa2yjT7pgWu2mDwlLvX1av+VCIQtZPnz4cUIWZPosS2d3jko37vb2A045ljLZzUSI69mjVBs83HpSubZymV+dF2Bh271a96bg/YsmlHpW3RdHz/sYOzeuXhI/T9FgufuKtzNX5Ijqj5elmLbUPX/R0k3qgSywTtWfWGpc0ksHyffytx/KzNCvPLPEVPZLXcYnTz/HatpBnuvs93auo0Tk/nU8MiRSZhdPUQC1CwAAAAB6OVh8AAAAACCrYPEBAAAAgKzS+2w+KmSd2xR4VUhu7fzHbT68Wu0bMvrsO+f+TsiW/vEHne7frx//lVNeceOtQta/pNgp53qkG6PWqJ09ypQTW6SslT21uFo+5qr74rYtWqMnVOjapkLHAecR1F2uoWlXNh9lzJOygdITVA9P25lwDba+PB8SbeNBSp0eaTUt7X3vLSHb8eZCp1yg/LjPHybtKq77urF/KCyUPVq1xdhuxHR/IsYeI2zJwVqyWfZn8Ws/YzWpo7764plO+dZ/vVzInn1xrqh/ut9MqI+WyzTajVuMvcqpZ0g3ysKRk0Xdw2wBvMpROJP/1VRWmYc9mIX5JiKiXPNS+5TZglsYdDfX2oQOWa4OTTJ5LKLdeVmagahye010PgmAlxlZeeLyM8xDpue6uPMSESX4m6AMt/ipiajsmx6dIPMd19Yh3M7FowbLH9AO4kcXG1j5ntekbOlKNpY7V0vhJ+tlfTu389D3zNMZZJBX4CgjmZJDInLY47oL7HwAAAAAIKtg8QEAAACArNLr1C7D5W43Rbinq1pKud1cistaiynnlQyhrrLwD8875ck1VS5HujsG1zAPrdNUhNUtbGdvtwxQSS1qpyzhoi7hu8RxrXZxUcOkqF24G656BjHVn4rOql3U8KREXGVlvdHJ70XvzOvVdivzFNzRfEjI4iwj7x33XS1k/3XvFOos3x7Jbkb589os0/GHO+XD3PSedtvjSP3Rgpf/xykXlUh/9NWbtZPhflYeI1utGO2UvwhJWbtVLupRdltadeHL4L81vhxT/nSnzObJn7NHTVJvBmoXH8/+qmR+Ndm4qiOprhljL008IZ8BV8mkvmtylsbZC+XmNh5Lyc4rr2mxFMoe5RZcxCKVnjRmnJANHyK/cXv31Dvl9R9sFLJ25nrrTUp9aNVgWV9F2eVlVX/gsY9EfcNLJpovbVWurk3MlbRtj5TZStdNvN3dmXSx19ASOyB/2MvUSZXps/x2Fex8AAAAACCrYPEBAAAAgKyCxQcAAAAAskqvs/k4MyTr7aHDH0fkrkv1q3orU13uLJH62eC53xL14tJip3zaGWcJ2YSvGd1q0+fSnbb0K10LUautQ8aypzbWxR6EiCjM6jrUOI+4HNE6anVNrrJOCenOz1PLWeU9StXMjEEG9pbkKW82r/Zi5CHmdR/YDzrKtkfN+P5fNa6c5w2VrqUTLzT1yWPJnTDrYKHyEy5gnd2xVYhySoxra+VAOT+GDpFh2t0x+uzf/M+MDo4dakqXfFdIRpxxqVNuUWOn3YQ9TK5dozNhL1PF7/hIZv70sDDl2qYhpvy4+5cag6KgzswaM3YLQTW52tvb0x6rXV05SeXb7/OZvnpVNlw9SRNkBpO71hLJvlva5kT5wHu8LC1EhYxDcOLIk5zykEHyQ5EIq7FjKSW8ueolYTYf+Wpcs/EPyAtqHt71k1ec8tY/vS6F7+9TZ/OUAHqSfsLKOhutymnhloL7GOW3/+8Zp/y9H36j29vHzgcAAAAAsgoWHwAAAADIKlh8AAAAACCr9Dqbj65H4HAn0t+Ul3uapXCIjG9w789+7pQLBqQPL7zo+aWiXt/U4pRPGKn87o//qjyZqYGH9KdOM0o9UR65WSbKJuIhUjoKCmylKROlhmNOdx5RasLpdAS12lnbkrhcn4fO96vzdJh2ngleq+kDTF28WWUOf3mejFKy9sWnnPJ/XHWekH3tePMAd3wkdcnePBNe/Qulh68oLRL1gaGLnfK+Vh3hIAMGX+kUR4yZJER8PAIdpCsIsrFMSdjucZsVkh0fm1gMXq968MzmwqvsLzz50kamtbXFKWs7Dk64pVXUK5StREW5sbUJ+KU9RpzF+djbJJ9l/T4TK6OwSPZN35fb+xSL6jfV0L+kRNRLWb0wX75dH7xnrKr+9MwzQrbtvQ9Efd8bLJS/+hZ9+7s3OOWgT1rLdVdw9Y9i8gWbPNWkEti3RsbuoJ11rKL/CVN2dX7Ww7gKimRzO49dUtZtd9Z72bJL2710L9j5AAAAAEBWyWjxMWfOHJowYQIVFhZSWVkZXX755bRt2zZxzKFDh2jatGk0YMAAKigooClTplBDg1ssSwAAAAD0JTJSu6xcuZKmTZtGEyZMoEQiQXfffTedf/75tGXLFsr/+xbozJkz6eWXX6aFCxdSKBSi6dOn0xVXXEFvv/32EbmBrrJzu6w/8aufOuUzz5Bhpcd973pRX/2hCcUbbpdbuO3NZqsqEpHbp96A2RJsDkvXrfqNH4p6Y7MJoxzKle51p440yqcRx0uVUP3HMkzwfqZbmXTmICEroPTYLjK9TSxCYCuZrru5P3N0ePWUhKGs4ZQEvC572lrtEuXh57WKhjUcliIqGSXH/czCO5yyVw4zRfymIU+e3PptCpt6OCzvJBCQW+zjJ9Q45T//RW1FC9TkJqlWqBo40ilXDiwWsmamLcnTqi4d4p6H1U9KlVFU+3W7MHioSUNQMVD2NRwx6hPdZGGp3GIPMJdV7er6WZ3Zqn/lT4uF7NC7a2XDeabdgaefLkTnfH2y6XeVTJ/AN+rLymSI+3ylImpsMs99x85PhOyEkeb5jBp1kpAl1UPYtsWEAX/zJZm2dfUzz5pKWM+J9FQNkWrDshLmwuxR4dU73ao7I/xSxfitC2ud8qavSJfz+j1m7LyePCH77eP3iHoNC8Vw9YxfCdnzv1jg0iOt4G897FFHOzf/4Gei/v47a5zy6refcz131n/8+xHp0z/IaPGxZMkSUX/yySeprKyMNmzYQGeffTa1trbSE088QfPnz6dzzz2XiIjmzZtHJ554Iq1evZpOVy8yAAAAAPoeX8rmo7X1b6vBkr8bPW3YsIHi8TjV1ppV68iRI6m6uppWrTp8yqFoNEptbW3iDwAAAADHLl1efFiWRTNmzKAzzzyTRo/+WybM+vp68vv9VFxcLI4tLy+n+vr6w7TyNzuSUCjk/FVVdddGHgAAAACORrrsajtt2jTavHkzvfXWWx0f7MLs2bNp1qxZTr2tre2ILUB4wuDlr7woZEv+9LRTfmXJYiF796N3RL22+rjDtklE9PhjL5k2X1smZM2fmwXY6JNHClnZQBn+ONxmdN1NO2Uq6HtWmPDCkah0h/ra8VJXuX2HOfdbN0od3g8fNuPuyREiUl6WrjK3Yzs6Nx1BFf8+ru0PWF1PYo+bzYeyW/BbaQ8VDaeYMKiLlrHHGdS2CewHT7HU/VuHWD1f3uSSd6Rdx5//spjVZF6B4tMud8ot7+p3Ui786zaalOmBaycLWUmxmT/KZIksSz49LrbUgHgs5rwts8CnMLra2GqsHSLf/eZWo2uPtMhd0fx8abVUUmJcmgsLpQ1BVdVgpzz+5FOEbMVS6RK/dNFip7zvdWkXsOB1NzsBc/28ETIe/70P3C/q21ebZ7Bs3k+E7MoVxv5rxCD5Pv/va9Ku47/vZ+d+1vWE9mdfe6dTvu72aUKWYG9GpPXI7Ey/r0wqhrMUBa1e+Y3L95pQCGWl0kboNJVug1uoVJSmd79O/YroMO284d5j/3HF1VeI+hmnHe+U4/XS3fqFl58W9UEnyHAQ3U2XFh/Tp0+nl156id544w0aPNi81BUVFRSLxailpUXsfjQ0NKT40v+DQCAgDMUAAAAAcGyTkdrFtm2aPn06LVq0iJYvX07Dhg0T8nHjxpHP56Nly8z/+Ldt20a7d++mmpoa3RwAAAAA+iAZ7XxMmzaN5s+fTy+88AIVFhY6dhyhUIiCwSCFQiG66aabaNasWVRSUkJFRUV02223UU1NzVHh6cJ3w79oki6PFYOGO+V390hZ2yHZThHz7tJx8MafZbL/hcqOE7JtWzc4Za9yEA03yy3B+jqz1VhRJbdeL7zyeqdcWird0G787vWiHmY7hM3NMnLrzk9N+Xi5juxx8pV+JsWdlpW1+6wIhKnVNWrGc7WLduflp3q1G67qH282RUXjMW6oJUXSVTHcbBpuT8rZ9FmTdvAtdkr9Tv22kHzvB5c7ZatOZqD8y+83iHoi37TrzZc6EU/QqEs8KgVwQrl58nG2dKpj/lA6ULvwAL4hFRk0xFxUo/2l67GvIE8da1QtqS7f5pfCQdIXesIZE0X9jgeMu+b7TEVFRLRwvnFfXf2iijK738QzOrR9uRDd+x1Zd+Pmr5/Q6WM7S8Goc0V9yBD5wv8rU7WUDZWqr/a4mb95VSqNdhdpC8st/1OHyMzhA9g3L6TUkXGmg136x8VC9rR6JseNNfrQj5dJlZVExXjOKRXVkaebObJ11Rvq3MPbMx4NHIzIf1cmn2ciGk+9WrmYUxFlk4wWH48++igREU2ePFn8Pm/ePLr++uuJiOjhhx8mj8dDU6ZMoWg0ShdccAH9+te/7pbOAgAAAKD3k9Hiw7bdQk/9jby8PJo7dy7NnTu3y50CAAAAwLELcrsAAAAAIKv0uqy2Xwau0TpnyjVCds2M7zrlQQPkebd9/xeiXsnSzE6+9Doh+/RjYy9SXCz1hud8/QKnXFEmZWOHU1paVJ07fSkP2Q4o6fiQowSd/TaubCyEN62ScXfajnKrco9ebcchUMt0fSi3CdH2KV/kGm+uQr+064iwhltj0m5i/NmTRb1wlAl7XTVmgpANGGKuESyTLqjDK2Uo+KaY0eFHyqQXWoTp0/3KjiOhfIj9HqMn9ym/3GgG/63hvm6F+XJ8/Cycd7BcvjM6Br+PGaH4VQ7eAMsqmxeUsk93yZQE4bCxiTllzGgh+2atcaFtp4eEbPMmE8L9+vP/Sfb18/epJ/nOzTeK+mnjpRtlXZ3J6nrKBGnzMZhZthV3U39+N/cx+UPrDlHd32pcXffTQXV2P1ZWtkafSR/9XfnMRuVg57O0FgyS78yts253yjs+ukjIfnnPDXS0su5N6XZfWWiee91aac901sXfVGdz+55MAip0Dux8AAAAACCrYPEBAAAAgKyCxQcAAAAAskqfsvngTDg1v+OD/k5jQ4Oov73WhDevGnmWkLW3Gx1kkqQe/KvHmbgfY6o7fflu07P2JnRcDR07g1e1jQVXT3o6MPrg7Xi0XYfL0lxFHhfnqogB1BQ3r1nUI61ZwsVGt+xRMeWHDZd65wqfmbMx9eYKG5iA7LinXMbDKGQWNR7VH5/HDF7ckiOr74t3waeejz8l2El6eLBqr1faY+QHTf8qSouFLKBCaXuYM15IGUNxyxb95lecIuN+/HW7iYfz5hIZn2PXHmPXMf5rMnBiScj076x/knYBb82rI8kXlE0em/EdUZ/w7X8T9XXPPemUL47K2BDFKtVBd3DZP8mw3zNn63AM2s6js7JPRS2+7dPDHtUR+eodOv/yM5zyrjoZOv9otvl48cmnRL1112anPHyQfBPOulh/8LrfzoODnQ8AAAAAZBUsPgAAAACQVfqs2iUT/mP2f4j6lg+3OuXGJpnhsH+h2aOsPf8kIRvUj0An8Shditsmvt7h5yobTwc7h1qVINrlS3O3EO5KbClZM/M7DVvSldQqNWGkvR65vx1X255cIWHpjjM9UMwrX+tooXS9pYTpTzAqr8F3m6MB5WpL2tXWlFUGghS1mRt8kz8YlOPDk04qEelA36VM1eKjznOcro8wLumXjLhAyN5joeJ/8lMZSPGP9/HvhB6RDBhwolMcOVGGft+6VoXE3v9Xp5hbcZoQJVvYt+mQdGVd91z6qNPTvnuHqD/wkx875XMHd08S0GGjzxP1CSecKOrrtv2VepJIm0xF0c4m6aCBaiJ6v2LKic+PYK+cC4ra0OpRov4Vljm7uFiqVWtON66235k6VbV7ZNUsGux8AAAAACCrYPEBAAAAgKyCxQcAAAAAsgpsPjrBhFNlWPKmBpOO+gsWlpiI6PxvGDcs2Hh0He26mWL0wWautrEQ7rO6Ge16y2wnXDWe+vqq4YQw+lDHBkzLUWXzcajzHqnCbVjbNHhYIPmEsmSxXAwggklpXJNkIdU9lg6ZLtv18BtVRjoej5s1jSTCyh5lTONlxiPaziXWTS6g2lWb26DoMP9j2DXvvneakNU3mtQKO/76kZAFVCj49tY2p3zaOBnq/Oc/v8cpq4DytCMs67fdbMJ+z5g1S8jOmWDsiX7/3Eoh+3DjJtn3fSacQD/l0vz/fve4U7aul2Haa6uV/UMXWbv1A1Gf/9xic/3HFwjZG6891y3XdKPt822ivuM9078Rxx8vD+6ynYf853fcaDMPas6Wc2L0ycauY/w46eo7bOgwUQ/mmbnm9cn3yZdX3KWeHgmw8wEAAACArILFBwAAAACyCtQuXeBr5w10ymdaA4Ws6AhEA+yLeFR0TZ9SJSS1roWfy9UBKToZqefwcTVDio7Gw2TyVfEqxYeb1sVND+Rn6hJLu7LqZpJmDKJaWcB8ii2Vy1dHeZXy9OoSS8msFMdkfqyLPqsDxMiqwfP5jFSrzJpjsh5hA6aVAVx9op9Ps6pztUtM3UaE6Ygsdf0fPvjDtNfQdT/T8ZUo9Szvq4w1SuRXXtOjmetkqxURMh63dfa3z5En6jpDR+/dcdijuhup9Pw/357ilPc2ymiw2VC7aB5/+KdOuX//9NnBzxh9qqif83UTAXvEcKkeOWXsGFEffbJR5wT6l6mWu8fFORPiMfP+80zP3QV2PgAAAACQVbD4AAAAAEBWweIDAAAAAFkFNh9doACjdsTxkNRfa1sNjye9/6i0P3DXvseJu5bKI3OFEYjUuSaV32cua0dbP1guBiHcrsJKduB3yxryKnuMdvb/CH9CtpOn7F4STL8eyZW9TbBraDsbbZPC7UUs7VrL2rXJHZ5xNuCTL1flANPXweo8PQNaWFnnjG1k5Xalvk6orvPHru84GjEWEQl1otWePoWyR8X5j3i4PZG0UClkSYj1p6ZYZeu9/fbrnHJYRXTnQQB0KHpt18GHpJXS064fZs5hD+sELaK2aMHjov7CK+uc8sKFS7t6kW5j1webnHLF6ZOEbPHC+U75wvOkG2ygP0+9rO02VFrmbgtvzp+u+o4eNPW2NikLx+QbFYua9zsaVwZO3QB2PgAAAACQVbD4AAAAAEBWweIDAAAAAFkF1gvgqMQTd7c34LE8UkN+8GN1+HB1HXas1rh6KL3yX9uH8AM8SaX7z2UtK5nF7QY6+K8AP9OjOpDgnVfqWU9SvuYJPnbqpj3MzkPblXhy5TOJsj54lBVBnN2L0jqnUMTKhYVFQlaa5rjDwS0ntHZ9LyuHlY1HNCr7HouZelJNGG7nYanAI9yuQ4eJd4t7YjXJa1glJiV6qYoBoluNuRjUNLGyDiGvNfg8noiOXxJ3M0XKc5G5IsfjaxOkrcTQKhPz4tbvytTvO3cYa5Y331wjZOHWFlEfUGpm0KBBMibTCSNHOuXqIdKiaH9zk6j7PWb2jT5JprAvHjyIjjzsCSXk04y3ykg1kYix4Eko4x7LMt+CSFS9z+pDGkuYiRCPaiuhLw92PgAAAACQVTJafDz66KN0yimnUFFRERUVFVFNTQ29+uqrjvzQoUM0bdo0GjBgABUUFNCUKVOooaHBpUUAAAAA9DUyUrsMHjyYHnroIRoxYgTZtk1PPfUUXXbZZbRx40Y66aSTaObMmfTyyy/TwoULKRQK0fTp0+mKK66gt99++0j1HxyjWIn0bp1ERJaVfi84ydQBqdoR7bLr4pabZO6QKWqf9Ot23TUP/0G56Fo8jLzSgSR0XHQXgszxNK4jyifVlj/rjl+JvKyvOjuuxyUUe8Inj/UyJVFHahdxnvoidXWzVwfA5q6kYRV73VJKGq524WUionicq13Sz0GfvpEM2N/Exi4/X8h8XjlHeBeSSg10KGKObdVh/ZVeins467s6xB5gijapy2oXma+3dPh5qp7+zElnm/LVN9yopC2yepA9+aB68Dl8bLWirnuy9UrU+2yr4PkHzMgfaJdvDVf3JZQKJBLRztFcLu8rEWMhAXTaBRWe32LXsRLd72qb0RtyySWXiPqDDz5Ijz76KK1evZoGDx5MTzzxBM2fP5/OPfdcIiKaN28enXjiibR69Wo6/fTTu6/XAAAAAOi1dNnmI5lM0oIFC6i9vZ1qampow4YNFI/Hqba21jlm5MiRVF1dTatWrUrbTjQapba2NvEHAAAAgGOXjBcfH3zwARUUFFAgEKBbbrmFFi1aRKNGjaL6+nry+/1UXFwsji8vL6f6+vq07c2ZM4dCoZDzV1VVlfFNAAAAAKD3kLFi8oQTTqBNmzZRa2srPffcczR16lRauXJllzswe/ZsmjVrllNva2vDAgRQxNKWAjouuVFYaj00NxexUoJwS1JdZtNcU+n33U5LDUPOr6ftSkw9Tvoays2Ty1Q7cYvbIshLxJRrXpKbmSg7E4v9f0TYo9DhbEdYXR2bcp8ucA21MokRob4LpYiKXdpsUXXeu69oOwU1f5KWsQXQrrZuNh+JuLlKTOnl9bFJVg8qW4T8/PTXz83t2ma116vfg/Q2DQFl/lDIBr5dmSkcObhBglvYcf2dUPfVj1v/uH8LOosdbhH1nIBpt6VJ7tx7xDVVKgNl17a3wbj3NrVKO47IAdOuziwRDMgfrIh5SNGovGZJqXE39it7olyPevABM9eCelJ0AxkvPvx+Px133HFERDRu3Dhat24d/eIXv6CrrrqKYrEYtbS0iN2PhoYGqqioSNMaUSAQoMARuDEAAAAAHJ186TgflmVRNBqlcePGkc/no2XLljmybdu20e7du6mmpubLXgYAAAAAxwgZ7XzMnj2bLrroIqqurqZwOEzz58+n119/nV577TUKhUJ000030axZs6ikpISKiorotttuo5qaGni6AAAAAMAho8VHY2MjXXfddbRv3z4KhUJ0yimn0GuvvUbf+MY3iIjo4YcfJo/HQ1OmTKFoNEoXXHAB/frXvz4iHQfHNmGlytVbdDyUtVaDJ5mKWFse6NAZuTz0uUfbPxh8qT2grqD7k2QhjRMd2JXwuo7pIPTJyk4gqdJh87Dg2jSDx7xIqoAhKbFXrPTXdIuBoeFK11P7S1mxy3naL66Rlfcr25Ews1XQNkLxmBzLg8ywgcdXIJL3FYnISdrOz1M2HynPlgVZ8Cu1cyHTxQcLpF4+qAJ0eNm5OqQ776u2HdHPxx9h/xQUy2vkMxuZqLI30GHb3RHWPS4yIjkr3GJuFGfUg/SoD46a6/N+9bhT/t833hGy40eaUPCRlgNCVlFmbCyCQTmuJ6ow7b/7/TNOec2GjULG0ynkh+ScuPA8GSNl5WtG+7Crrk7ILp5yqelbVaWQ6TAkhcwWyYp1v7FPRouPJ554wlWel5dHc+fOpblz536pTgEAAADg2AW5XQAAAACQVZDVFhyV7N6jw5nLPUE/CzOtZcSyr+Z6dTsS7oHoUToZH3Px83v8qh2dDtacm5urQ7izitptjnLXzYTOkqo6K1yItRsuy0AZl5vhCZXaMsGumVTb77FEkB2nPw/p3UU7ci3tLMUZHKuz3PL6INX1HSFTblLRqIvy5bMcNMC0pLRAIvvrZ/VynBubjKtkWbkMHx5XqWEPhk3Yb60uKSsz7qFDQ0KU4izKW21SMp60NCXkv5pbXOOYmyNlSZY5t0Jl2c3MeZUHuc/EcToTpHogedCoU7QqLM4GxVKy/IBU9axdu94pr1i2Qsh4vTQkA/tHmCpOq+lum3G7qK9Zvc70lSStrebptrbJb5F2v17/vmnnkGrpTwsXOuXPW78QsoI8OdmEu3xcjuvM+2fTlwU7HwAAAADIKlh8AAAAACCrYPEBAAAAgKySY9u23fFh2aOtrY1CoRDdddddiHwKAAAA9BKi0Sg99NBD1NraSkVF2ipLgp0PAAAAAGQVLD4AAAAAkFWw+AAAAABAVsHiAwAAAABZBYsPAAAAAGSVoy7C6T+cb6JRnWgIAAAAAEcr//h3uzNOtEedq+1nn31GVVVVPd0NAAAAAHSBuro6Gjx4sOsxR93iw7Is2rt3L9m2TdXV1VRXV9ehv3BfpK2tjaqqqjA+acD4uIPxcQfj4w7GJz19eWxs26ZwOEyVlZUpOYs0R53axePx0ODBg6mtrY2IiIqKivrcA8wEjI87GB93MD7uYHzcwfikp6+OTSgU6vgggsEpAAAAALIMFh8AAAAAyCpH7eIjEAjQAw88gPwuacD4uIPxcQfj4w7Gxx2MT3owNp3jqDM4BQAAAMCxzVG78wEAAACAYxMsPgAAAACQVbD4AAAAAEBWweIDAAAAAFkFiw8AAAAAZJWjdvExd+5cGjp0KOXl5dGkSZNo7dq1Pd2lrDNnzhyaMGECFRYWUllZGV1++eW0bds2ccyhQ4do2rRpNGDAACooKKApU6ZQQ0NDD/W4Z3nooYcoJyeHZsyY4fzW18dnz5499J3vfIcGDBhAwWCQTj75ZFq/fr0jt22b7r//fho4cCAFg0Gqra2l7du392CPs0cymaT77ruPhg0bRsFgkIYPH04//vGPRVKsvjQ+b7zxBl1yySVUWVlJOTk5tHjxYiHvzFg0NzfTtddeS0VFRVRcXEw33XQTHThwIIt3ceRwG594PE533nknnXzyyZSfn0+VlZV03XXX0d69e0Ubx/L4ZIx9FLJgwQLb7/fbv/vd7+wPP/zQ/t73vmcXFxfbDQ0NPd21rHLBBRfY8+bNszdv3mxv2rTJ/uY3v2lXV1fbBw4ccI655ZZb7KqqKnvZsmX2+vXr7dNPP90+44wzerDXPcPatWvtoUOH2qeccop9++23O7/35fFpbm62hwwZYl9//fX2mjVr7E8++cR+7bXX7I8//tg55qGHHrJDoZC9ePFi+7333rMvvfRSe9iwYXYkEunBnmeHBx980B4wYID90ksv2Tt37rQXLlxoFxQU2L/4xS+cY/rS+Lzyyiv2PffcYz///PM2EdmLFi0S8s6MxYUXXmiPGTPGXr16tf3mm2/axx13nH3NNddk+U6ODG7j09LSYtfW1trPPvusvXXrVnvVqlX2xIkT7XHjxok2juXxyZSjcvExceJEe9q0aU49mUzalZWV9pw5c3qwVz1PY2OjTUT2ypUrbdv+24T3+Xz2woULnWP++te/2kRkr1q1qqe6mXXC4bA9YsQIe+nSpfY555zjLD76+vjceeed9llnnZVWblmWXVFRYf/sZz9zfmtpabEDgYD9zDPPZKOLPcrFF19s33jjjeK3K664wr722mtt2+7b46P/ce3MWGzZssUmInvdunXOMa+++qqdk5Nj79mzJ2t9zwaHW5xp1q5daxORvWvXLtu2+9b4dIajTu0Si8Vow4YNVFtb6/zm8XiotraWVq1a1YM963laW1uJiKikpISIiDZs2EDxeFyM1ciRI6m6urpPjdW0adPo4osvFuNAhPF58cUXafz48XTllVdSWVkZjR07ln7729868p07d1J9fb0Yn1AoRJMmTeoT43PGGWfQsmXL6KOPPiIiovfee4/eeustuuiii4gI48PpzFisWrWKiouLafz48c4xtbW15PF4aM2aNVnvc0/T2tpKOTk5VFxcTEQYH81Rl9W2qamJkskklZeXi9/Ly8tp69atPdSrnseyLJoxYwadeeaZNHr0aCIiqq+vJ7/f70zuf1BeXk719fU90Mvss2DBAnr33Xdp3bp1KbK+Pj6ffPIJPfroozRr1iy6++67ad26dfT973+f/H4/TZ061RmDw71rfWF87rrrLmpra6ORI0dSbm4uJZNJevDBB+naa68lIurz48PpzFjU19dTWVmZkHu9XiopKelz43Xo0CG688476ZprrnEy22J8JEfd4gMcnmnTptHmzZvprbfe6umuHDXU1dXR7bffTkuXLqW8vLye7s5Rh2VZNH78ePrJT35CRERjx46lzZs302OPPUZTp07t4d71PH/84x/p6aefpvnz59NJJ51EmzZtohkzZlBlZSXGB3SZeDxO//zP/0y2bdOjjz7a0905ajnq1C6lpaWUm5ub4pHQ0NBAFRUVPdSrnmX69On00ksv0YoVK2jw4MHO7xUVFRSLxailpUUc31fGasOGDdTY2EinnXYaeb1e8nq9tHLlSvrlL39JXq+XysvL+/T4DBw4kEaNGiV+O/HEE2n37t1ERM4Y9NV37Qc/+AHddddddPXVV9PJJ59M//Iv/0IzZ86kOXPmEBHGh9OZsaioqKDGxkYhTyQS1Nzc3GfG6x8Lj127dtHSpUudXQ8ijI/mqFt8+P1+GjduHC1btsz5zbIsWrZsGdXU1PRgz7KPbds0ffp0WrRoES1fvpyGDRsm5OPGjSOfzyfGatu2bbR79+4+MVbnnXceffDBB7Rp0ybnb/z48XTttdc65b48PmeeeWaKa/ZHH31EQ4YMISKiYcOGUUVFhRiftrY2WrNmTZ8Yn4MHD5LHIz+Bubm5ZFkWEWF8OJ0Zi5qaGmppaaENGzY4xyxfvpwsy6JJkyZlvc/Z5h8Lj+3bt9Nf/vIXGjBggJD39fFJoactXg/HggUL7EAgYD/55JP2li1b7JtvvtkuLi626+vre7prWeXWW2+1Q6GQ/frrr9v79u1z/g4ePOgcc8stt9jV1dX28uXL7fXr19s1NTV2TU1ND/a6Z+HeLrbdt8dn7dq1ttfrtR988EF7+/bt9tNPP23369fP/sMf/uAc89BDD9nFxcX2Cy+8YL///vv2ZZdddsy6kmqmTp1qDxo0yHG1ff755+3S0lL7jjvucI7pS+MTDoftjRs32hs3brSJyP75z39ub9y40fHW6MxYXHjhhfbYsWPtNWvW2G+99ZY9YsSIY8aV1G18YrGYfemll9qDBw+2N23aJL7X0WjUaeNYHp9MOSoXH7Zt27/61a/s6upq2+/32xMnTrRXr17d013KOkR02L958+Y5x0QiEfvf/u3f7P79+9v9+vWzv/Wtb9n79u3ruU73MHrx0dfH589//rM9evRoOxAI2CNHjrR/85vfCLllWfZ9991nl5eX24FAwD7vvPPsbdu29VBvs0tbW5t9++2329XV1XZeXp791a9+1b7nnnvEPxZ9aXxWrFhx2O/N1KlTbdvu3Fjs37/fvuaaa+yCggK7qKjIvuGGG+xwONwDd9P9uI3Pzp07036vV6xY4bRxLI9PpuTYNgvnBwAAAABwhDnqbD4AAAAAcGyDxQcAAAAAsgoWHwAAAADIKlh8AAAAACCrYPEBAAAAgKyCxQcAAAAAsgoWHwAAAADIKlh8AAAAACCrYPEBAAAAgKyCxQcAAAAAsgoWHwAAAADIKv8fLxH5Bgl0rPcAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "plane plane plane car  \n"
     ]
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# functions to show an image\n",
    "def imshow(img):\n",
    "    img = img / 2 + 0.5 # un-normalize\n",
    "    np_img = img.numpy()\n",
    "    plt.imshow(np.transpose(np_img, (1, 2, 0)))\n",
    "    plt.show()\n",
    "\n",
    "# get some random training images\n",
    "dataiter = iter(trainloader)\n",
    "images, labels = next(dataiter)\n",
    "images = images[:4]\n",
    "labels = labels[:4]\n",
    "\n",
    "# show images\n",
    "imshow(torchvision.utils.make_grid(images))\n",
    "# print labels\n",
    "print(' '.join(f'{classes[labels[j]]:5s}' for j in range(4)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a7e5af5",
   "metadata": {
    "id": "4a7e5af5"
   },
   "source": [
    "## Model Class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "8483d0f3",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "8483d0f3",
    "outputId": "17919148-abd2-4614-8a89-f1585cf44414"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Resetting Layer:  Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "Resetting Layer:  Linear(in_features=25088, out_features=4096, bias=True)\n",
      "Resetting Layer:  Linear(in_features=4096, out_features=4096, bias=True)\n",
      "Resetting Layer:  Linear(in_features=4096, out_features=10, bias=True)\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torchvision\n",
    "\n",
    "class PreTrainedNet(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.pretrained_vgg11 = torchvision.models.vgg11(weights=\"DEFAULT\")\n",
    "        self.pretrained_vgg11.classifier[6] = nn.Linear(4096, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.pretrained_vgg11(x)\n",
    "\n",
    "    @staticmethod\n",
    "    def reset_model_weights(layer):\n",
    "      if hasattr(layer, 'reset_parameters'):\n",
    "        print('Resetting Layer: ',layer)\n",
    "        layer.reset_parameters()\n",
    "      elif hasattr(layer, 'children'):\n",
    "        for child in layer.children():\n",
    "          PreTrainedNet.reset_model_weights(child)\n",
    "\n",
    "    def reset_weights(self):\n",
    "      for child in self.children():\n",
    "        PreTrainedNet.reset_model_weights(child)\n",
    "\n",
    "model_with_reset_weights = PreTrainedNet()\n",
    "model_with_reset_weights.reset_weights()\n",
    "model_with_reset_weights.train()\n",
    "\n",
    "model_with_reset_weights = model_with_reset_weights.to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "f599310f",
   "metadata": {
    "id": "f599310f"
   },
   "outputs": [],
   "source": [
    "import torch.optim as optim\n",
    "\n",
    "criterion_new = nn.CrossEntropyLoss()\n",
    "optimizer_new = optim.SGD(model_with_reset_weights.parameters(),\n",
    "                          lr=0.05, momentum=0.9)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "078e8c85",
   "metadata": {
    "id": "078e8c85"
   },
   "source": [
    "### Training Loop (with Reset Weights Model)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "473c5c44",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "473c5c44",
    "outputId": "8e38161d-08df-4f69-8b31-1d9683b12c30"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1,   100] loss: 2.303\n",
      "[2,   100] loss: 2.295\n",
      "[3,   100] loss: 2.303\n",
      "[4,   100] loss: 2.217\n",
      "[5,   100] loss: 1.845\n",
      "[6,   100] loss: 1.545\n",
      "[7,   100] loss: 1.221\n",
      "[8,   100] loss: 0.970\n",
      "[9,   100] loss: 0.767\n",
      "[10,   100] loss: 0.623\n",
      "Finished Training\n"
     ]
    }
   ],
   "source": [
    "# Set model to train mode\n",
    "model_with_reset_weights.train()\n",
    "\n",
    "for epoch in range(10):  # loop over the dataset multiple times\n",
    "    running_loss = 0.0\n",
    "    for i, data in enumerate(trainloader, 0):\n",
    "        # get the inputs; data is a list of [inputs, labels]\n",
    "        inputs, labels = data[0].to(device), data[1].to(device)\n",
    "\n",
    "        # zero the parameter gradients\n",
    "        optimizer_new.zero_grad()\n",
    "\n",
    "        # forward + backward + optimize\n",
    "        outputs = model_with_reset_weights(inputs)\n",
    "        loss = criterion_new(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer_new.step()\n",
    "\n",
    "        # print statistics\n",
    "        running_loss += loss.item()\n",
    "        if i % 100 == 99:    # print every 2000 mini-batches\n",
    "            print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 100:.3f}')\n",
    "            running_loss = 0.0\n",
    "\n",
    "print('Finished Training')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0772505",
   "metadata": {
    "id": "b0772505"
   },
   "source": [
    "### Accuracy per Class (Training Model from Scratch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "1bb43a13",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "1bb43a13",
    "outputId": "8a1c27be-c408-48d9-daf1-722cd317903f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy for class: plane is 88.7 %\n",
      "Accuracy for class: car   is 89.2 %\n",
      "Accuracy for class: bird  is 55.4 %\n",
      "Accuracy for class: cat   is 43.6 %\n",
      "Accuracy for class: deer  is 76.5 %\n",
      "Accuracy for class: dog   is 65.5 %\n",
      "Accuracy for class: frog  is 84.1 %\n",
      "Accuracy for class: horse is 90.7 %\n",
      "Accuracy for class: ship  is 76.8 %\n",
      "Accuracy for class: truck is 77.8 %\n"
     ]
    }
   ],
   "source": [
    "# prepare to count predictions for each class\n",
    "correct_pred = {classname: 0 for classname in classes}\n",
    "total_pred = {classname: 0 for classname in classes}\n",
    "\n",
    "# set model to eval mode\n",
    "model_with_reset_weights.eval()\n",
    "\n",
    "# again no gradients needed\n",
    "with torch.no_grad():\n",
    "    for data in testloader:\n",
    "        images, labels = data[0].to(device), data[1].to(device)\n",
    "        outputs = model_with_reset_weights(images)\n",
    "        _, predictions = torch.max(outputs, 1)\n",
    "        # collect the correct predictions for each class\n",
    "        for label, prediction in zip(labels, predictions):\n",
    "            if label == prediction:\n",
    "                correct_pred[classes[label]] += 1\n",
    "            total_pred[classes[label]] += 1\n",
    "\n",
    "\n",
    "# print accuracy for each class\n",
    "for classname, correct_count in correct_pred.items():\n",
    "    accuracy = 100 * float(correct_count) / total_pred[classname]\n",
    "    print(f'Accuracy for class: {classname:5s} is {accuracy:.1f} %')\n",
    "    ACCURACY_COMPARE[classname].update({'from_scratch': accuracy})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "HLxXVFeqmY9Z",
   "metadata": {
    "id": "HLxXVFeqmY9Z"
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "8gtYS-k6mV4r",
   "metadata": {
    "id": "8gtYS-k6mV4r"
   },
   "source": [
    "# Model with Pretrained Weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "D8yZf7wcHYbW",
   "metadata": {
    "id": "D8yZf7wcHYbW"
   },
   "outputs": [],
   "source": [
    "model_with_pretrained_weights = PreTrainedNet()\n",
    "# Not resetting the weights\n",
    "model_with_pretrained_weights.train()\n",
    "\n",
    "model_with_pretrained_weights = model_with_pretrained_weights.to(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8DuWTPVsmarb",
   "metadata": {
    "id": "8DuWTPVsmarb"
   },
   "source": [
    "#### Optimizer has Learning Rate 50x smaller than the previous model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "eEInwU8-dIpo",
   "metadata": {
    "id": "eEInwU8-dIpo"
   },
   "outputs": [],
   "source": [
    "import torch.optim as optim\n",
    "\n",
    "criterion_new = nn.CrossEntropyLoss()\n",
    "optimizer_new = optim.SGD(model_with_pretrained_weights.parameters(),\n",
    "                          lr=0.001, momentum=0.9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "I01uLWr-dpG_",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "I01uLWr-dpG_",
    "outputId": "5716f9cd-7d9b-4a70-9c56-7494d754edcb"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1,   100] loss: 1.303\n",
      "[2,   100] loss: 0.675\n",
      "[3,   100] loss: 0.550\n",
      "[4,   100] loss: 0.473\n",
      "[5,   100] loss: 0.418\n",
      "[6,   100] loss: 0.361\n",
      "[7,   100] loss: 0.307\n",
      "[8,   100] loss: 0.262\n",
      "[9,   100] loss: 0.231\n",
      "[10,   100] loss: 0.200\n",
      "Finished Training\n"
     ]
    }
   ],
   "source": [
    "# Set model to train model\n",
    "model_with_pretrained_weights.train()\n",
    "\n",
    "for epoch in range(10):  # loop over the dataset multiple times\n",
    "    running_loss = 0.0\n",
    "    for i, data in enumerate(trainloader, 0):\n",
    "        # get the inputs; data is a list of [inputs, labels]\n",
    "        inputs, labels = data[0].to(device), data[1].to(device)\n",
    "\n",
    "        # zero the parameter gradients\n",
    "        optimizer_new.zero_grad()\n",
    "\n",
    "        # forward + backward + optimize\n",
    "        outputs = model_with_pretrained_weights(inputs)\n",
    "        loss = criterion_new(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer_new.step()\n",
    "\n",
    "        # print statistics\n",
    "        running_loss += loss.item()\n",
    "        if i % 100 == 99:    # print every 2000 mini-batches\n",
    "            print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 100:.3f}')\n",
    "            running_loss = 0.0\n",
    "\n",
    "print('Finished Training')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "dsEyIzsgdp-M",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "dsEyIzsgdp-M",
    "outputId": "4e092c35-952c-4953-9313-e31a8f53257a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy for class: plane is 88.2 %\n",
      "Accuracy for class: car   is 92.7 %\n",
      "Accuracy for class: bird  is 76.0 %\n",
      "Accuracy for class: cat   is 69.5 %\n",
      "Accuracy for class: deer  is 85.3 %\n",
      "Accuracy for class: dog   is 75.2 %\n",
      "Accuracy for class: frog  is 90.8 %\n",
      "Accuracy for class: horse is 87.0 %\n",
      "Accuracy for class: ship  is 90.7 %\n",
      "Accuracy for class: truck is 90.8 %\n"
     ]
    }
   ],
   "source": [
    "# prepare to count predictions for each class\n",
    "correct_pred = {classname: 0 for classname in classes}\n",
    "total_pred = {classname: 0 for classname in classes}\n",
    "\n",
    "# set model to eval mode\n",
    "model_with_pretrained_weights.eval()\n",
    "\n",
    "# again no gradients needed\n",
    "with torch.no_grad():\n",
    "    for data in testloader:\n",
    "        images, labels = data[0].to(device), data[1].to(device)\n",
    "        outputs = model_with_pretrained_weights(images)\n",
    "        _, predictions = torch.max(outputs, 1)\n",
    "        # collect the correct predictions for each class\n",
    "        for label, prediction in zip(labels, predictions):\n",
    "            if label == prediction:\n",
    "                correct_pred[classes[label]] += 1\n",
    "            total_pred[classes[label]] += 1\n",
    "\n",
    "\n",
    "# print accuracy for each class\n",
    "for classname, correct_count in correct_pred.items():\n",
    "    accuracy = 100 * float(correct_count) / total_pred[classname]\n",
    "    print(f'Accuracy for class: {classname:5s} is {accuracy:.1f} %')\n",
    "    ACCURACY_COMPARE[classname].update({'fine-tuned': accuracy})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "XtEy4gbSfr00",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "XtEy4gbSfr00",
    "outputId": "ecc768ac-6875-442d-8f0d-24daff4103c5"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "defaultdict(dict,\n",
       "            {'plane': {'from_scratch': 88.7, 'fine-tuned': 88.2},\n",
       "             'car': {'from_scratch': 89.2, 'fine-tuned': 92.7},\n",
       "             'bird': {'from_scratch': 55.4, 'fine-tuned': 76.0},\n",
       "             'cat': {'from_scratch': 43.6, 'fine-tuned': 69.5},\n",
       "             'deer': {'from_scratch': 76.5, 'fine-tuned': 85.3},\n",
       "             'dog': {'from_scratch': 65.5, 'fine-tuned': 75.2},\n",
       "             'frog': {'from_scratch': 84.1, 'fine-tuned': 90.8},\n",
       "             'horse': {'from_scratch': 90.7, 'fine-tuned': 87.0},\n",
       "             'ship': {'from_scratch': 76.8, 'fine-tuned': 90.7},\n",
       "             'truck': {'from_scratch': 77.8, 'fine-tuned': 90.8}})"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ACCURACY_COMPARE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "4DsTmJFWkpQG",
   "metadata": {
    "id": "4DsTmJFWkpQG"
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "accuracy_df = pd.DataFrame(ACCURACY_COMPARE)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "qV6DZgXcmjfw",
   "metadata": {
    "id": "qV6DZgXcmjfw"
   },
   "source": [
    "# Comparison of Accuracy by Class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "eyWw61ZEllW5",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 492
    },
    "id": "eyWw61ZEllW5",
    "outputId": "d4b09a31-82f2-45b2-b2e3-d2e938207ec2"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: >"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAAG1CAYAAABZMpbEAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3P0lEQVR4nO3dd3xUVf7/8fckkAYpEEgBAwllpUkRRED9goIgotLWXRQVUHEFDNKLSgtVdoHQpEjXRVRYESzIGgEFaRIQVAQCiYlAggUSiiEhub8/+DHLmAAZSO7NTF7Px2MeD+bcOzOf60xm3p577jk2wzAMAQAAmMTD6gIAAEDJQvgAAACmInwAAABTET4AAICpCB8AAMBUhA8AAGAqwgcAADBVKasL+LPc3FydOHFC/v7+stlsVpcDAAAKwDAMnT17VpUqVZKHx/X7Nopd+Dhx4oQiIiKsLgMAANyElJQU3Xbbbdfdp9iFD39/f0mXiw8ICLC4GgAAUBAZGRmKiIiw/45fT7ELH1dOtQQEBBA+AABwMQUZMsGAUwAAYCrCBwAAMBXhAwAAmKrYjfkA3E1OTo6ys7OtLgPFWOnSpeXp6Wl1GYBpCB9AETEMQ6mpqTpz5ozVpcAFBAUFKSwsjPmNUCIQPoAiciV4hISEyM/Pjx8V5MswDF24cEGnTp2SJIWHh1tcEVD0CB9AEcjJybEHj+DgYKvLQTHn6+srSTp16pRCQkI4BQO3x4BToAhcGePh5+dncSVwFVc+K4wPQklA+ACKEKdaUFB8VlCSED4AAICpCB8AAMBUDDgFTBY54mPTXitpSgenH2MYhv7xj39o9erVOn36tPbu3auGDRsWfnFuzGaz6YMPPlCnTp2sLgUoluj5AOBgw4YNWrZsmT766COdPHlS9erVs7okyyQlJclms2nfvn1WlwK4FXo+ADg4evSowsPD1aJFi3y3Z2VlycvLy+SqCpc7HAPgyuj5AGDXs2dPRUdHKzk5WTabTZGRkWrVqpVeeuklDRgwQBUqVFC7du0kSVu2bFHTpk3l7e2t8PBwjRgxQpcuXbI/V6tWrRQdHa0BAwaoXLlyCg0N1Ztvvqnz58+rV69e8vf3V40aNfTpp58WqLbTp0+re/fuqlixonx9fVWzZk0tXbrUvv3nn3/WE088ofLly6tMmTJq0qSJdu7cKUkaO3asGjZsqEWLFikqKko+Pj6SLvfy3HvvvQoKClJwcLAeeeQRHT161P6cUVFRkqRGjRrJZrOpVatW9m1LlixR3bp17cf/0ksvOdT766+/qnPnzvLz81PNmjW1bt06J94JwL3R8+HqxgY6uX960dQBtzBz5kxVr15dCxcu1O7du+Xp6anHH39cy5cvV58+fbRt2zZJ0vHjx/Xwww+rZ8+eWrFihX788Uf17t1bPj4+Gjt2rP35li9frmHDhmnXrl1699131adPH33wwQfq3LmzXnnlFc2YMUNPP/20kpOTbzgnyqhRo/TDDz/o008/VYUKFZSQkKA//vhDknTu3Dm1bNlSlStX1rp16xQWFqb4+Hjl5ubaH5+QkKA1a9boP//5j30Sr/Pnz2vQoEGqX7++zp07p9GjR6tz587at2+fPDw8tGvXLjVt2lSff/656tata+8tmTdvngYNGqQpU6aoffv2Sk9Pt/+3uWLcuHGaOnWq/vnPf2r27Nnq3r27fvrpJ5UvX/6W3yfA1RE+ANgFBgbK399fnp6eCgsLs7fXrFlTU6dOtd9/9dVXFRERoTlz5shms6lWrVo6ceKEhg8frtGjR8vD43KnaoMGDfTaa69JkkaOHKkpU6aoQoUK6t27tyRp9OjRmjdvnvbv369mzZpdt7bk5GQ1atRITZo0kSRFRkbat61cuVK//PKLdu/ebf9xr1GjhsPjs7KytGLFClWsWNHe1rVrV4d9lixZoooVK+qHH35QvXr17PsGBwc7/PeYMGGCBg8erJdfftnedtdddzk8V8+ePfXEE09IkiZNmqRZs2Zp165deuihh657nEBJwGkXADfUuHFjh/sHDx5U8+bNHSbGuueee3Tu3Dn9/PPP9rb69evb/+3p6ang4GDdcccd9rbQ0FBJsq9rcj19+vTRqlWr1LBhQw0bNkxff/21fdu+ffvUqFGj6/YqVK1a1SF4SNKRI0f0xBNPqFq1agoICLAHmuTk5Gs+z6lTp3TixAm1bt36uvVefexlypRRQEBAgY4TKAkIHwBuqEyZMjf1uNKlSzvct9lsDm1XwsvVp0eupX379vrpp580cOBA+4//kCFDJP1vbZTrye8YHn30Uf3+++968803tXPnTvsYkaysrGs+T0FeS8r/2AtynEBJQPgA4LTatWtr+/btMgzD3rZt2zb5+/vrtttuK7LXrVixonr06KG3335bsbGxWrhwoaTLvQz79u3T77//XuDn+u2333To0CG99tprat26tWrXrq3Tp0877HNljEdOTo69zd/fX5GRkYqLiyuEIwJKJsIHAKf17dtXKSkpio6O1o8//qgPP/xQY8aM0aBBg+zjPQrb6NGj9eGHHyohIUHff/+9PvroI9WuXVuS9MQTTygsLEydOnXStm3bdOzYMa1Zs0bbt2+/5vOVK1dOwcHBWrhwoRISEvTFF19o0KBBDvuEhITI19dXGzZsUFpamtLTLw/YHjt2rKZNm6ZZs2bpyJEjio+P1+zZs4vkuAF3xIBTwGQ3M+tocVO5cmV98sknGjp0qBo0aKDy5cvrueeesw8uLQpeXl4aOXKkkpKS5Ovrq/vuu0+rVq2yb9u4caMGDx6shx9+WJcuXVKdOnU0d+7caz6fh4eHVq1apf79+6tevXq6/fbbNWvWLIfLaUuVKqVZs2YpJiZGo0eP1n333afNmzerR48eyszM1IwZMzRkyBBVqFBBf/3rX4vs2AF3YzOu7jctBjIyMhQYGKj09HQFBARYXU7xx6W2xVJmZqYSExMd5pQAriffz0wx/Pt2dnkAdwjbkorle3FTivA4nPn95rQLAAAwFeEDQLHw4osvqmzZsvneXnzxRavLA1CIGPMBoFiIiYmxXzr7Z5yCBdwL4QNAsRASEqKQkBCrywBgAk67AAAAU9HzUYw4O4pckpK4kAIA4GLo+QAAAKZym56PEnvtOQAALoaeDwAAYCq36flwmrOzvEnFd8Y6uJab+ezd9Gs5/5k1DEP/+Mc/tHr1ap0+fVqBgYHq2bOnYmNjC7++Ymzz5s26//77dfr0aQUFBVldDuBWSm74AJCvDRs2aNmyZdq8ebOqVasmDw+PAi8jfytatWqlhg0blriQA5REhA8ADo4eParw8HC1aNHC6lIAuCnGfACw69mzp6Kjo5WcnCybzabIyEi1atVKAwYMsO8TGRmpSZMm6dlnn5W/v7+qVKmihQsXOjxPSkqK/va3vykoKEjly5dXx44dlZSUdN3X3bJli2bOnCmbzSabzaakpCQtW7YszymPtWvXymaz2e+PHTtWDRs21FtvvaXIyEgFBgaqW7duOnv2rH2f3NxcTZ48WVFRUfL19VWDBg20evVqh+f95JNP9Je//EW+vr66//77r1svgFtDzwcAu5kzZ6p69epauHChdu/eLU9PTz3++ON59ps2bZrGjx+vV155RatXr1afPn3UsmVL3X777crOzla7du3UvHlzffXVVypVqpQmTJighx56SPv375eXl1e+r3v48GHVq1dPMTExkqSKFSsWuO6jR49q7dq1+uijj3T69Gn97W9/05QpUzRx4kRJ0uTJk/X2229r/vz5qlmzpr788ks99dRTqlixolq2bKmUlBR16dJF/fr10wsvvKBvvvlGgwcPvsn/inDA+Drkg/ABwC4wMFD+/v7y9PRUWFjYNfd7+OGH1bdvX0nS8OHDNWPGDG3atEm333673n33XeXm5mrRokX2HoqlS5cqKChImzdvVtu2bfN9XS8vL/n5+V33da8lNzdXy5Ytk7+/vyTp6aefVlxcnCZOnKiLFy9q0qRJ+vzzz9W8eXNJUrVq1bR161YtWLBALVu21Lx581S9enVNmzZNknT77bfrwIEDev31152uBcCNET4AOK1+/fr2f9tsNoWFhenUqVOSpG+//VYJCQn2IHBFZmamjh49qq+++krt27e3ty9YsEDdu3e/pXoiIyMdXi88PNxeT0JCgi5cuKAHH3zQ4TFZWVlq1KiRJOngwYO6++67HbZfCSoACh/hA4DTSpcu7XDfZrMpNzdXknTu3Dk1btxY//73v/M8rmLFivLy8tK+ffvsbaGhodd8HQ8PDxmG4dCWnZ3tdD2S9PHHH6ty5coO+3l7e1/ztQEUHcIHgEJ155136t1331VISIgCAgLy3adGjRp52ry8vJSTk+PQVrFiRZ09e1bnz59XmTJlJMkhuBREnTp15O3treTkZLVs2TLffWrXrq1169Y5tO3YscOp1wFQcFztAqBQde/eXRUqVFDHjh311VdfKTExUZs3b1b//v31888/X/NxkZGR2rlzp5KSkvTrr78qNzdXd999t/z8/PTKK6/o6NGjWrlypZYtW+ZUPf7+/hoyZIgGDhyo5cuX6+jRo4qPj9fs2bO1fPlySdKLL76oI0eOaOjQoTp06NBNvQ6AgqPnAzCbm4/k9/Pz05dffqnhw4erS5cuOnv2rCpXrqzWrVtfsydEkoYMGaIePXqoTp06+uOPP5SYmKjIyEi9/fbbGjp0qN588021bt1aY8eO1QsvvOBUTePHj1fFihU1efJkHTt2TEFBQbrzzjv1yiuvSJKqVKmiNWvWaODAgZo9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SVq6dKlq166tHTt2qFmzZoVXOQAAcEm3NOYjPT1dklS+fHlJ0p49e5Sdna02bdrY96lVq5aqVKmi7du35/scFy9eVEZGhsMNAAC4r5sOH7m5uRowYIDuuece1atXT5KUmpoqLy8vBQUFOewbGhqq1NTUfJ9n8uTJCgwMtN8iIiJutiQAAOACbjp89OvXT999951WrVp1SwWMHDlS6enp9ltKSsotPR8AACjenBrzccVLL72kjz76SF9++aVuu+02e3tYWJiysrJ05swZh96PtLQ0hYWF5ftc3t7e8vb2vpkyAACAC3Kq58MwDL300kv64IMP9MUXXygqKsphe+PGjVW6dGnFxcXZ2w4dOqTk5GQ1b968cCoGAAAuzamej379+mnlypX68MMP5e/vbx/HERgYKF9fXwUGBuq5557ToEGDVL58eQUEBCg6OlrNmzfnShcAACDJyfAxb948SVKrVq0c2pcuXaqePXtKkmbMmCEPDw917dpVFy9eVLt27fTGG28USrEAAMD1ORU+DMO44T4+Pj6aO3eu5s6de9NFAQAA98XaLgAAwFSEDwAAYCrCBwAAMBXhAwAAmIrwAQAATEX4AAAApiJ8AAAAUxE+AACAqQgfAADAVIQPAABgKsIHAAAwFeEDAACYivABAABMRfgAAACmInwAAABTET4AAICpCB8AAMBUhA8AAGAqwgcAADAV4QMAAJiK8AEAAExF+AAAAKYifAAAAFMRPgAAgKkIHwAAwFSEDwAAYCrCBwAAMBXhAwAAmIrwAQAATEX4AAAApiJ8AAAAUxE+AACAqQgfAADAVIQPAABgKsIHAAAwFeEDAACYivABAABMRfgAAACmInwAAABTET4AAICpCB8AAMBUhA8AAGAqwgcAADAV4QMAAJiK8AEAAExF+AAAAKYifAAAAFMRPgAAgKkIHwAAwFSEDwAAYCrCBwAAMBXhAwAAmIrwAQAATEX4AAAApiJ8AAAAUxE+AACAqQgfAADAVIQPAABgKsIHAAAwFeEDAACYivABAABMRfgAAACmInwAAABTET4AAICpCB8AAMBURRY+5s6dq8jISPn4+Ojuu+/Wrl27iuqlAACACymS8PHuu+9q0KBBGjNmjOLj49WgQQO1a9dOp06dKoqXAwAALqRIwsf06dPVu3dv9erVS3Xq1NH8+fPl5+enJUuWFMXLAQAA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VpdYolSsWFGzZs3SE0884dD+zjvvKDo6uth3+buLrKws9evXT8uWLVNOTo5KlSqlS5cuqXv37lq2bJnLTE1euXJlbdy4Mc/VOd99953atm2rEydOWFTZ9e3fv1/16tWTh4eH7r///mvuZ7PZXOLSzivGjRt33e2uEGr/+OMP5ebm2oNTUlKS1q5dq9q1a6tdu3YWV3dr3nrrLQ0fPtzSv4sSEz6qVKmiFStWqFWrVgoICFB8fLxq1Kiht956S++8844++eQTq0ssUYKCgrR7927VrFnTof3w4cNq2rSpzpw5Y01hJVRKSooOHDigc+fOqVGjRnnel+LO399f69evV6tWrRzaN23apMceeyzfOUCKA09PT508eVIhISGqVq2adu/ereDgYKvLgqS2bds6TBFfq1YtlS5duthPEX+1P59GMgxDJ0+e1DfffKNRo0ZZGgJLzJiP33//XdWqVZN0eXzHle6me++91yU+RO7m6aef1rx58/J0JS9cuJBeqCJ2o4GaO3bssP/bVbr6O3furF69emnatGkO83wMHTo0zxdwcRIUFKTExESFhIQoKSnJLSbfu9qePXscFvr789Uvxdmfp4gPDQ11iSnirxYYGOhw38PDQ7fffrtiYmIsX+CvxISPatWqKTExUVWqVFGtWrX03nvvqWnTplq/fr3LzAHg6q7+0bPZbFq0aJE2btyoZs2aSbr8Y5GcnOzyq90Wd+42UFOS5s+fryFDhujJJ59Udna2pMurJz/33HP65z//aXF119a1a1e1bNnSPolVkyZNrnmq69ixYyZXd/NOnTqlbt26afPmzfbv1zNnzuj+++/XqlWrVLFiRWsLLIALFy7YLz/fuHGjunTpIg8PDzVr1kw//fSTxdXdWE5Ojnr16qU77rjDPg6qOCkxp11mzJghT09P9e/fX59//rkeffRRGYah7OxsTZ8+XS+//LLVJbq9653Tvpqrnd92Ze4wUPNq58+f19GjRyVdnjb+zwMdi6MNGzYoISFB/fv3V0xMjMN8K1dzpe+ov//97zp27JhWrFih2rVrS5J++OEH9ejRQzVq1NA777xjcYU3Vr9+fT3//PPq3Lmz6tWrpw0bNqh58+bas2ePOnTooNTUVKtLvKFrTYRYLJi/nEzxkJSUZKxZs8b49ttvrS4FsEylSpWM7777Lk/7gQMHjPDwcAsqKrl69uxpZGRkWF1GoQgICDB27dqVp33nzp1GYGCg+QXdhPfff98oXbq04eHhYTz44IP29kmTJhkPPfSQhZUVXOPGjY3PP//c6jLyVWJOu/xZ1apVVbVqVavLACyVkZGhX375JU/7L7/8UmwHaborV750889yc3PzzIshXZ6AzFXGtfz1r3/Vvffea58i/orWrVurc+fOFlZWcBMmTNCQIUM0fvz4fC/ftnJ+K7c+7XKj9UOu5grTeQOF7ZlnntFXX32V70DN++67T8uXL7e4Qriijh076syZM3rnnXfsSw0cP35c3bt3V7ly5fTBBx9YXGHJcGVNHclxBmnDMGSz2Syd38qtw0dBz3PZbDaXGswFFJYLFy5oyJAhWrJkSb4DNV1hzASKn5SUFD322GP6/vvvFRERIUlKTk7WHXfcoXXr1um2226zuMKSYfny5YqIiMgziDk3N1fJycmWTrHu1uHjWgwXXUsEKCquOFATxZthGIqLi3NY6K9NmzYWV1WyXD2PzNV+++03hYSE0PNhFldfSwQAXEVcXJzi4uJ06tSpPOM8lixZYlFVJYuHh4fS0tLyXNr8008/qU6dOjp//rxFlZWgeT6utZbIwIEDlZyc7FJriQBAcTZu3DjFxMSoSZMm9jlMYJ4rcyrZbDaNGjVKfn5+9m05OTnauXNnnhVvzVZiej5YSwQAzBEeHq6pU6fq6aeftrqUEunKnEpbtmxR8+bN5eXlZd/m5eWlyMhIDRkyxNJlFEpMz0d2draaNGmSp71x48a6dOmSBRUBgHvKyspSixYtrC6jxNq0aZOky6v0zpw509JLaq/F48a7uIcra4n8GWuJAEDhev7557Vy5Uqryyjxli5dWiyDh1SCTrtER0drxYoVioiIyHctkasnxHGVxbQAoLi4eu2m3NxcLV++XPXr11f9+vXzTDjGdyxKTPhgXREAKDp8x8IZJSZ8AACA4qHEjPkAAADFA+EDAACYivABAABMRfgAAACmInwAAABTET4AAICpCB8AAMBU/w+SLRsWOVNSkgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "accuracy_df.T.plot(kind='bar')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ulw9vOrTll_N",
   "metadata": {
    "id": "ulw9vOrTll_N"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "torch",
   "language": "python",
   "name": "torch"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
